package com.cxh.supermarket.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cxh.supermarket.common.constant.CacheNames;
import com.cxh.supermarket.system.domain.SysRegion;
import com.cxh.supermarket.system.domain.vo.AllRegionVo;
import com.cxh.supermarket.system.mapper.SysRegionMapper;
import com.cxh.supermarket.system.service.SysRegionService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * 行政区划
 *
 * @author shichunjie
 * @since 2024/1/19
 */
@RequiredArgsConstructor
@Service
public class SysRegionServiceImpl extends ServiceImpl<SysRegionMapper, SysRegion> implements SysRegionService {

  private final SysRegionMapper regionMapper;

  /**
   * 根据code查询子列表信息
   *
   * @param code 区域code
   * @return 子列表
   */
  @Cacheable(cacheNames = CacheNames.SYS_REGION, key = "#code")
  @Override
  public List<SysRegion> selectList(String code) {
    SysRegion region = this.getById(code);
    List<SysRegion> sysRegions = regionMapper.selectList(Wrappers.<SysRegion>query().lambda().eq(SysRegion::getParentCode, code));
    SysRegion sysRegion = new SysRegion();
    sysRegion.setCode(code);
    sysRegion.setName("全" + region.getName());
    sysRegion.setSimpleName("全" + region.getSimpleName());
    sysRegion.setParentCode(code);
    sysRegion.setLat(region.getLat());
    sysRegion.setLng(region.getLng());
    sysRegion.setProvinceName(region.getProvinceName());
    sysRegion.setProvinceCode(region.getProvinceCode());
    sysRegions.add(0, sysRegion);
    return sysRegions;
  }

  /**
   * 行政区划根据code查询坐标
   */
  @Override
  public SysRegion selectCoordinate(String code) {
    return this.getOne(new LambdaQueryWrapper<SysRegion>()
        .select(SysRegion::getLat, SysRegion::getLng)
        .eq(SysRegion::getCode, code));
  }

  /**
   * 行政区划根据code查询数据
   *
   * @param code
   */
  @Override
  public SysRegion selectSysRegion(String code) {
    if (ObjectUtil.isNotNull(code)) {
      return this.getById(code);
    }
    return null;
  }

  /**
   * 查询所有行政区划
   */
  @Override
  @Cacheable(value = CacheNames.SYS_REGION_ALL, key = "#root.method.name")
  public List<AllRegionVo> getAll() {
    //查询一级
    List<SysRegion> oneList = this.lambdaQuery().select(SysRegion::getCode, SysRegion::getName, SysRegion::getSimpleName,
            SysRegion::getLat, SysRegion::getLng, SysRegion::getParentCode)
        .eq(SysRegion::getRegionLevel, 1).list();
    //查询二级
    List<SysRegion> twoList =
        this.lambdaQuery().select(SysRegion::getCode, SysRegion::getName, SysRegion::getSimpleName, SysRegion::getParentCode,
                SysRegion::getLat, SysRegion::getLng, SysRegion::getParentCode)
            .eq(SysRegion::getRegionLevel, 2).list();

    //查询二级
    List<SysRegion> threeList =
        this.lambdaQuery().select(SysRegion::getCode, SysRegion::getName, SysRegion::getSimpleName, SysRegion::getParentCode,
                SysRegion::getLat, SysRegion::getLng, SysRegion::getParentCode)
            .eq(SysRegion::getRegionLevel, 3).list();

    List<AllRegionVo> list = new ArrayList<>();
    //循环一级
    for (SysRegion sysRegion : oneList) {
      AllRegionVo allRegionVo =
          new AllRegionVo(sysRegion.getCode(), sysRegion.getName(), sysRegion.getSimpleName(), sysRegion.getLat(), sysRegion.getLng(),
              sysRegion.getParentCode(), "");
      List<AllRegionVo> children2 = new ArrayList<>();
      //循环二级
      for (SysRegion sysRegion2 : twoList) {
        if (sysRegion2.getParentCode().equals(sysRegion.getCode())) {


          AllRegionVo allRegionVo2 =
              new AllRegionVo(sysRegion2.getCode(), sysRegion2.getName(), sysRegion2.getSimpleName(), sysRegion2.getLat(),
                  sysRegion2.getLng(), sysRegion2.getParentCode(), sysRegion.getName());
          List<AllRegionVo> children3 = new ArrayList<>();

          //循环三级
          for (SysRegion sysRegion3 : threeList) {
            if (sysRegion3.getParentCode().equals(sysRegion2.getCode())) {
              AllRegionVo allRegionVo3 =
                  new AllRegionVo(sysRegion3.getCode(), sysRegion3.getName(), sysRegion3.getSimpleName(), sysRegion3.getLat(),
                      sysRegion3.getLng(), sysRegion3.getParentCode(), allRegionVo2.getName());
              children3.add(allRegionVo3);
            }

          }
          AllRegionVo quanCity =
              new AllRegionVo(sysRegion2.getCode(), "全" + sysRegion2.getName(), "全" + sysRegion2.getSimpleName(), sysRegion2.getLat(),
                  sysRegion2.getLng(), sysRegion2.getParentCode(), sysRegion2.getName());
          children3.add(0, quanCity);
          //三级放入二级中
          allRegionVo2.setCityList(children3);
          children2.add(allRegionVo2);

        }
      }
      AllRegionVo quanProvince =
          new AllRegionVo(sysRegion.getCode(), "全" + sysRegion.getName(), "全" + sysRegion.getSimpleName(), sysRegion.getLat(),
              sysRegion.getLng(), sysRegion.getParentCode(), sysRegion.getName());
      children2.add(0, quanProvince);
      //二级放入一级中
      allRegionVo.setCityList(children2);
      list.add(allRegionVo);

    }
    return list;

       /* List<AllRegionVo> one = oneList.stream().map(t -> new AllRegionVo(t.getCode(), t.getName(), t.getSimpleName(), t.getLat(), t.getLng())).collect(Collectors.toList());

        List<AllRegionVo> two = twoList.stream().map(t -> {
            AllRegionVo region = new AllRegionVo(t.getCode(), t.getName(), t.getSimpleName(), t.getLat(), t.getLng());
            region.setParentCode(t.getParentCode());
            return region;
        }).collect(Collectors.toList());

        //组合数据
        one.forEach(t -> {
            List<AllRegionVo> city = new ArrayList<>();
            two.forEach(l -> {
                if (t.getCode().equals(l.getParentCode())) {
                    city.add(l);
                }
            });
            //添加全省
            AllRegionVo regionVo = new AllRegionVo(t.getCode(), "全" + t.getName(), "全" + t.getSimpleName(), t.getLat(), t.getLng());
            regionVo.setParentCode(t.getCode());
            city.add(0, regionVo);
            t.setChildList(city);
        });
        return one;*/
  }

  /**
   * 查询所有行政区划（没有全山东）
   */
  @Override
  @Cacheable(value = CacheNames.SYS_REGION_ALL_A, key = "#root.method.name")
  public List<AllRegionVo> getAllA() {
    //查询一级
    List<SysRegion> oneList = this.lambdaQuery().select(SysRegion::getCode, SysRegion::getName, SysRegion::getSimpleName,
            SysRegion::getLat, SysRegion::getLng, SysRegion::getParentCode)
        .eq(SysRegion::getRegionLevel, 1).list();
    //查询二级
    List<SysRegion> twoList =
        this.lambdaQuery().select(SysRegion::getCode, SysRegion::getName, SysRegion::getSimpleName, SysRegion::getParentCode,
                SysRegion::getLat, SysRegion::getLng, SysRegion::getParentCode)
            .eq(SysRegion::getRegionLevel, 2).list();

    //查询二级
    List<SysRegion> threeList =
        this.lambdaQuery().select(SysRegion::getCode, SysRegion::getName, SysRegion::getSimpleName, SysRegion::getParentCode,
                SysRegion::getLat, SysRegion::getLng, SysRegion::getParentCode)
            .eq(SysRegion::getRegionLevel, 3).list();

    List<AllRegionVo> list = new ArrayList<>();
    //循环一级
    for (SysRegion sysRegion : oneList) {
      AllRegionVo allRegionVo =
          new AllRegionVo(sysRegion.getCode(), sysRegion.getName(), sysRegion.getSimpleName(), sysRegion.getLat(), sysRegion.getLng(),
              sysRegion.getParentCode(), "");
      List<AllRegionVo> children2 = new ArrayList<>();
      //循环二级
      for (SysRegion sysRegion2 : twoList) {
        if (sysRegion2.getParentCode().equals(sysRegion.getCode())) {


          AllRegionVo allRegionVo2 =
              new AllRegionVo(sysRegion2.getCode(), sysRegion2.getName(), sysRegion2.getSimpleName(), sysRegion2.getLat(),
                  sysRegion2.getLng(), sysRegion2.getParentCode(), sysRegion.getName());
          List<AllRegionVo> children3 = new ArrayList<>();

          //循环三级
          for (SysRegion sysRegion3 : threeList) {
            if (sysRegion3.getParentCode().equals(sysRegion2.getCode())) {
              AllRegionVo allRegionVo3 =
                  new AllRegionVo(sysRegion3.getCode(), sysRegion3.getName(), sysRegion3.getSimpleName(), sysRegion3.getLat(),
                      sysRegion3.getLng(), sysRegion3.getParentCode(), allRegionVo2.getName());
              children3.add(allRegionVo3);
            }

          }
          AllRegionVo quanCity =
              new AllRegionVo(sysRegion2.getCode(), "全" + sysRegion2.getName(), "全" + sysRegion2.getSimpleName(), sysRegion2.getLat(),
                  sysRegion2.getLng(), sysRegion2.getParentCode(), sysRegion2.getName());
          children3.add(0, quanCity);
          //三级放入二级中
          allRegionVo2.setCityList(children3);
          children2.add(allRegionVo2);

        }
      }
          /*  AllRegionVo quanProvince= new AllRegionVo(sysRegion.getCode(), "全" +sysRegion.getName(), "全" +sysRegion.getSimpleName(), sysRegion.getLat(), sysRegion.getLng());
            children2.add(0,quanProvince);*/
      //二级放入一级中
      allRegionVo.setCityList(children2);
      list.add(allRegionVo);

    }
    return list;
  }


  /**
   * 通过 行政规划code 查询 行政规划名称
   *
   * @param codes 行政规划code串逗号分隔
   * @return 行政规划名称拼接
   */
  @Override
  @Cacheable(value = CacheNames.SYS_REGION_NAME, key = "#codes", sync = true)
  public String selectRegionNameByCodes(String codes) {
    List<String> list = new ArrayList<>();
    for (String code : Arrays.stream(codes.split(",")).map(String::toString).collect(Collectors.toList())) {
      SysRegion sysRegion = regionMapper.selectOne(new LambdaQueryWrapper<SysRegion>()
          .select(SysRegion::getSimpleName).eq(SysRegion::getCode, code));
      if (ObjectUtil.isNotNull(sysRegion)) {
        list.add(sysRegion.getSimpleName());
      }
    }
    return String.join("", list);
  }

  /**
   * 通过 行政规划code 查询 行政规划名称 带横杠
   *
   * @param codes 行政规划code串逗号分隔
   * @return 行政规划名称拼接
   */
  @Override
  @Cacheable(value = CacheNames.SYS_REGION_NAME_UNDERLINE, key = "#codes", sync = true)
  public String selectRegionNameByCodesAndUnderline(String codes) {
    List<String> list = new ArrayList<>();
    for (String code : Arrays.stream(codes.split(",")).map(String::toString).collect(Collectors.toList())) {
      SysRegion sysRegion = regionMapper.selectOne(new LambdaQueryWrapper<SysRegion>()
          .select(SysRegion::getName).eq(SysRegion::getCode, code));
      if (ObjectUtil.isNotNull(sysRegion)) {
        list.add(sysRegion.getName());
      }
    }
    return String.join("-", list);
  }

  /**
   * 根据省名称查询数据
   *
   * @param provinceName 省名称
   * @return 省数据
   */
  @Override
  public SysRegion selectDataByProvinceName(String provinceName) {

    return regionMapper.selectOne(new LambdaQueryWrapper<SysRegion>().like(SysRegion::getName, provinceName).last("limit 1"));
  }

  /**
   * 根据市名称查询数据
   *
   * @param cityName
   * @return
   */
  @Override
  public SysRegion selectCityNameByData(String cityName) {
    return regionMapper.selectOne(new LambdaQueryWrapper<SysRegion>().like(SysRegion::getName, cityName).last("limit 1"));
  }

  /**
   * 根据城市省code加市或区县名称名称查询数据
   *
   * @param provinceCode 省code
   * @param countyName   市或区县名称
   * @return 数据
   */
  @Override
  public SysRegion selectSysRegionByProvinceCodeAndCountyName(String provinceCode, String countyName) {
    if (ObjectUtil.isNotEmpty(countyName)) {
      return regionMapper.selectOne(
          new LambdaQueryWrapper<SysRegion>().eq(SysRegion::getProvinceCode, provinceCode).like(SysRegion::getName, countyName)
              .last("limit 1"));
    }
    return null;
  }

  /**
   * 根据市code加区县名称查询数据
   *
   * @param cityCode   市code
   * @param countyName 区县名称
   * @return
   */
  @Override
  public SysRegion selectSysRegionByData(String cityCode, String countyName) {
    if (ObjectUtil.isNotEmpty(countyName)) {
      return regionMapper.selectOne(
          new LambdaQueryWrapper<SysRegion>().eq(SysRegion::getParentCode, cityCode).like(SysRegion::getName, countyName).last("limit 1"));
    }
    return null;
  }
}
